package com.atguigu.gmall.activity.receiver;

import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.UserRecode;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;

@Component
public class SeckillReceiver {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private SeckillGoodsService seckillGoodsService;

    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_1,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK),
            key = {MqConst.ROUTING_TASK_1}
    ))
    public void importToRedisData(String msg, Message message, Channel channel){
        try {
            System.out.println(msg);
            //  扫描当天秒杀的商品！ 系统时间与秒杀开始时间 比较 ， status = 1 ，必须有剩余库存>0
            QueryWrapper<SeckillGoods> seckillGoodsQueryWrapper = new QueryWrapper<>();
            seckillGoodsQueryWrapper.eq("status",1);
            seckillGoodsQueryWrapper.gt("stock_count",0);
            //  select date_format(start_time,'%Y-%m-%d')  from seckill_goods; new Date(); 秒杀开始时间要和系统时间为同一天
            seckillGoodsQueryWrapper.eq("date_format(start_time,'%Y-%m-%d')", DateUtil.formatDate(new Date()));
            //  查询秒杀商品
            List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(seckillGoodsQueryWrapper);
            //  将秒杀商品放入缓存！
            if (!CollectionUtils.isEmpty(seckillGoodsList)){
                //  循环遍历
                for (SeckillGoods seckillGoods : seckillGoodsList) {
                    //  存储到缓存 ： 数据类型 hash  hset  key=seckill:goods  field=skuId  value=seckillGoods  hget key  field，key
                    String seckillKey = RedisConst.SECKILL_GOODS;
                    //  判断key 中是否有 field！
                    Boolean flag = this.redisTemplate.opsForHash().hasKey(seckillKey,seckillGoods.getSkuId().toString());
                    //  key 中有 field！
                    if(flag){
                        //  不需要再次写入缓存！
                        //  break;跳出循环   continue;结束本次循环   return; 结束方法！
                        continue;
                    }
                    //  将商品放入缓存！
                    this.redisTemplate.opsForHash().put(seckillKey,seckillGoods.getSkuId().toString(),seckillGoods);
                    //  细节：如何防止库存超卖！ 将商品的数量放入缓存中！ 10
                    for (Integer i = 0; i < seckillGoods.getStockCount(); i++) {
                        //  list  key = seckill:stock:skuId  value = skuId    seckill:stock:skuId 22
                    redisTemplate.opsForList().leftPush(RedisConst.SECKILL_STOCK_PREFIX +seckillGoods.getSkuId(),seckillGoods.getSkuId().toString());
                    }

                    //  初始化skuId 为可以秒杀状态！ skuId:1
                    this.redisTemplate.convertAndSend("seckillpush",seckillGoods.getSkuId()+":1");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //  手动确认
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    //  监听哪个用户秒杀的哪个商品！
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_SECKILL_USER,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_SECKILL_USER),
            key = {MqConst.ROUTING_SECKILL_USER}
    ))
    public void seckillUser(UserRecode userRecode , Message message , Channel channel){
        try {
            //  判断
            if(userRecode!=null){
                //  预下单处理！
                seckillGoodsService.seckillOrder(userRecode.getUserId(),userRecode.getSkuId());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //  手动确认
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    //  删除缓存中的数据：
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_18,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK),
            key = {MqConst.ROUTING_TASK_18}
    ))
    public void delRedisData(String msg, Message message, Channel channel){
        try {
            System.out.println(msg);
            //  删除数据！   哪些数据要被删除?  status = 1 ; new Date()  > endTime();
            QueryWrapper<SeckillGoods> seckillGoodsQueryWrapper = new QueryWrapper<>();
            seckillGoodsQueryWrapper.eq("status","1");
            seckillGoodsQueryWrapper.lt("end_time",new Date());
            //  查询秒杀结束的商品！
            List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(seckillGoodsQueryWrapper);
            //  循环遍历
            for (SeckillGoods seckillGoods : seckillGoodsList) {
                this.redisTemplate.delete(RedisConst.SECKILL_STOCK_PREFIX+seckillGoods.getSkuId());
            }

            //  删除缓存中 所有数据！ 商品数据！
            this.redisTemplate.delete(RedisConst.SECKILL_GOODS);

            //  删除用户真正秒杀的订单数据！
            this.redisTemplate.delete(RedisConst.SECKILL_ORDERS_USERS);

            //  预下单数据什么时候删除的? 真正下单的时候就删除这个数据！ 删除预下单数据
            this.redisTemplate.delete(RedisConst.SECKILL_ORDERS);

            //  需要将数据库中的这个秒杀商品状态更新为 2 ，意味着秒杀结束了！
            SeckillGoods seckillGoods = new SeckillGoods();
            seckillGoods.setStatus("2");
            this.seckillGoodsMapper.update(seckillGoods,seckillGoodsQueryWrapper);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //  手动确认
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
}
